/**
<code>
  <author name="Zealic" email="zealic(at)gmail.com" type="Creator"/>
</code>
**/
using System;
using System.Text;
using System.IO;
using System.Data;


namespace Zealib.Utilities
{
    /// <summary>
    /// CSV(Comma separated values) file writer.
    /// </summary>
    public class CsvWriter : IDisposable
    {
        private StreamWriter m_Writer;

        /// <summary>
        /// Create a <see cref="CsvWriter"/>.
        /// </summary>
        /// <param name="stream">Writer stream</param>
        public CsvWriter(Stream stream)
            : this(stream, Encoding.UTF8)
        {
        }

        /// <summary>
        /// Create a <see cref="CsvWriter"/>.
        /// </summary>
        /// <param name="stream">Writer stream</param>
        /// <param name="encoding">Encoding</param>
        public CsvWriter(Stream stream, Encoding encoding)
        {
            if (stream == null) throw new ArgumentNullException("stream");
            if (encoding == null) throw new ArgumentNullException("encoding");
            m_Writer = new StreamWriter(stream, encoding);
        }

        public CsvWriter(string filename)
            : this(File.OpenWrite(filename))
        {
        }


        public static void SaveDataTable(string filename, DataTable table)
        {
            using (var writer = new CsvWriter(filename))
                foreach (DataRow row in table.Rows)
                {
                    writer.WriteRow(row.ItemArray);
                }
        }

        /// <summary>
        /// Write a row.
        /// </summary>
        /// <param name="cells">cells of value.</param>
        public void WriteRow(params object[] cells)
        {
            if (cells == null) throw new ArgumentNullException("cells");
            string[] strCells = new string[cells.Length];
            for (int i = 0; i < cells.Length; i++)
            {
                object cell = cells[i];
                if (cell == null || cell == DBNull.Value)
                {
                    strCells[i] = "";
                    continue;
                }
                strCells[i] = cell.ToString();
            }
            WriteRow(strCells);
        }

        /// <summary>
        /// Write a row.
        /// </summary>
        /// <param name="cells">cells of value.</param>
        public virtual void WriteRow(params string[] cells)
        {
            if (cells == null) throw new ArgumentNullException("cells");
            int cellCount = cells.Length;
            for (int n = 0; n < cellCount; n++)
            {
                m_Writer.Write("\"");
                m_Writer.Write(EscapeCell(cells[n]));
                m_Writer.Write("\"");
                if (n != (cellCount - 1))
                    m_Writer.Write(",");
            }
            m_Writer.WriteLine();
        }

        /// <summary>
        /// Flush base stream.
        /// </summary>
        public void Flush()
        {
            m_Writer.Flush();
        }

        // Get escaped cell value.
        private static string EscapeCell(string content)
        {
            return content.Replace("\"", "\"\"");
        }

        public void Dispose()
        {
            if (m_Writer != null)
            {
                m_Writer.Close();
                m_Writer = null;
            }
        }

    }
}
